package lexer

import (
	"fmt"
	"strings"
)

// Lexer 结构体，用于词法分析
type Lexer struct {
	// 输入字符串
	input string
	// 当前字符的位置
	position int

	// 下一个字符的位置
	readPosition int

	// 当前字符
	ch byte
	// 行号
	line int
}

// 创建一个新的Lexer对象，参数为输入的字符串
func NewLexer(input string) *Lexer {
	// 创建一个新的Lexer对象，并将输入的字符串赋值给对象的input字段
	l := &Lexer{input: input, line: 1}
	// 调用readChar()方法，读取输入字符串的第一个字符
	l.readChar()
	// 返回创建的Lexer对象
	return l
}

func (l *Lexer) readChar() {
	if l.readPosition >= len(l.input) {
		l.ch = 0
	} else {
		l.ch = l.input[l.readPosition]
	}
	l.position = l.readPosition
	l.readPosition++
}

func (l *Lexer) NextToken() Token {
	l.skipWhitespace()
	var tok Token

	switch l.ch {
	case '>':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			literal := string(ch) + string(l.ch)
			tok = Token{Type: LARGE_GT, Literal: literal}
		} else {
			tok = newToken(LT, l.ch, l.line)
		}
	case '<':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			literal := string(ch) + string(l.ch)
			tok = Token{Type: SMALL_GT, Literal: literal}
		} else {
			tok = newToken(GT, l.ch, l.line)
		}
	case '(':
		tok = newToken(LPAREN, l.ch, l.line)
	case ')':
		tok = newToken(RPAREN, l.ch, l.line)
	case '[':
		tok = newToken(LBRACKET, l.ch, l.line)
	case ']':
		tok = newToken(RBRACKET, l.ch, l.line)
	case '{':
		tok = newToken(LBRACE, l.ch, l.line)
	case '}':
		tok = newToken(RBRACE, l.ch, l.line)
	case '\'':
		tok = newToken(SQ, l.ch, l.line)
	case '"':
		tok = newToken(DQ, l.ch, l.line)
	case '=':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			literal := string(ch) + string(l.ch)
			tok = Token{Type: EQ, Literal: literal}
		} else {
			tok = newToken(ASSIGN, l.ch, l.line)
		}
	case ';':
		tok = newToken(SEMICOLON, l.ch, l.line)
	case 0:
		tok.Literal = ""
		tok.Type = EOF
	default:
		if isLetter(l.ch) {
			tok.Literal = l.readIdentifier()
			tok.Type = LookupIdent(tok.Literal)
			tok.Line = l.line
			return tok
		} else if isDigit(l.ch) {
			tok.Literal = l.readNumber()
			tok.Type = INT
			if strings.Contains(tok.Literal, ".") {
				tok.Type = FLOAT
			}
			tok.Line = l.line
			return tok
		}
	}
	l.readChar()
	return tok
}

func newToken(tokenType TokenType, ch byte, line int) Token {
	return Token{Type: tokenType, Literal: string(ch), Line: line}
}

// 判断字符是否为字母
func isLetter(ch byte) bool {
	// 如果字符在'0'和'9'之间，并且字符等于46（即'.'），则返回true
	return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_'
}
func (l *Lexer) readIdentifier() string {
	position := l.position
	for isLetter(l.ch) {
		l.readChar()
	}
	return l.input[position:l.position]
}

// 判断字符是否为数字
func isDigit(ch byte) bool {
	// 如果字符在'0'和'9'之间，并且字符等于46（即'.'），则返回true
	return ch >= '0' && ch <= '9' || ch == 46
}
func (l *Lexer) readNumber() string {
	position := l.position
	for isDigit(l.ch) {
		l.readChar()
	}
	return l.input[position:l.position]
}

func (l *Lexer) skipWhitespace() {
	//\t	水平制表符
	// \n换行
	//\r	回车符
	for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
		if l.ch == '\n' || l.ch == '\r' {
			l.line++
			fmt.Printf("%d,Character: %c\n", l.ch, l.ch)
			fmt.Println(l.line)
		}
		l.readChar()
		// fmt.Printf("%d,Character: %c\n", l.ch, l.ch)
	}
}

// 下一个字符
func (l *Lexer) peekChar() byte {
	if l.readPosition >= len(l.input) {
		return 0
	} else {
		return l.input[l.readPosition]
	}
}
